Skip to content

feat: add @nest-native/cache read caching (ninth library)#61

Merged
rodrigobnogueira merged 1 commit into
mainfrom
feat/stalefree-cache
Jul 20, 2026
Merged

feat: add @nest-native/cache read caching (ninth library)#61
rodrigobnogueira merged 1 commit into
mainfrom
feat/stalefree-cache

Conversation

@rodrigobnogueira

Copy link
Copy Markdown
Contributor

What

Dogfoods the brand-new @stalefree/core + @nest-native/cache (published tonight, 0.1.0), bringing the reference app to 9/9 nest-native libraries: expensive reads cached in an in-memory L1 with tag-based invalidation — mutations evict by tag, and every entry's TTL is only the delivery backstop.

The pattern (the chapter readers copy)

  • Cache at the API seam, not the service: projects.list/get and activity.list wrap their synchronous services with org-scoped keys (org:7:project:42) and tags — services stay cache-free and sync.
  • Invalidate at the write sites: projects.create evicts the org's project tag; ActivityService.record invalidates the project's feed tag at the projection write site — the event-driven feed evicts its own cache when the outbox handler writes the row. (Sync better-sqlite3 transactions mean no mid-tx interleaving, so pre-commit invalidation is unobservable here; the caveat for async drivers is documented inline.)
  • Coherence by deployment shape: single process (default profile) needs no bus; setting CACHE_SOCKET_PATH wires @stalefree/core/socket's unix-socket mesh for the app + start:worker split — the same-machine tier built for exactly this topology.

Proof

test/e2e/stalefree-cache.spec.ts runs with a ten-minute TTL, so stale data would be glaring for the whole run:

  1. projects.list cached → projects.create → the next read reflects the new project immediately (tag invalidation, provably not expiry)
  2. activity.list cached → tasks.create → claimer tick → the feed shows the event row immediately — the projection's write-site invalidation working end to end

Feedback-loop note

No library friction to ship upstream this time — the two lessons earlier dogfoods taught (useFactory: (...args: any[]), full provider exports) were baked into @nest-native/cache from day one, and both held. A pre-publish two-agent adversarial review of the core had already caught and fixed 2 criticals + 4 real defects, which is likely why this integration went through clean.

Gates

typecheck, lint, complexity (≤15), client-smoke, 86 pass / 0 fail (live-Kafka spec self-skips — Docker not run for this PR). README + constitution reframed eight → nine.

Dogfood @stalefree/core + @nest-native/cache: expensive reads cached in an
in-memory L1 with tag-based invalidation, TTL as the delivery backstop.

- cache.setup.ts: CacheModule.forRootAsync; the socket bus is wired when
  CACHE_SOCKET_PATH is set (the app + start:worker split — the same-machine
  tier built for exactly this shape); in-process coherence otherwise
- projects.router: list/get wrapped with org-scoped keys + tags; create
  invalidates the org's project tag (typed useFactory + explicit @Inject —
  both lessons the earlier dogfoods taught are already honored upstream)
- activity.router: the feed cached per project; ActivityService.record
  invalidates at the projection write site — the event-driven feed evicts its
  own cache when the handler writes (sync better-sqlite3 tx: no mid-tx
  interleaving, so pre-commit invalidation is unobservable here; documented)
- env: CACHE_TTL_MS (default 30s) + CACHE_SOCKET_PATH (optional)
- e2e: a TEN-MINUTE TTL makes staleness glaring; both specs prove freshness
  within seconds of the mutation — tag invalidation, not expiry
- README + constitution reframed eight -> nine libraries/chapters

Gates: typecheck, lint, complexity, client-smoke, 86 pass / 0 fail (live-
Kafka spec self-skips without Docker).
@rodrigobnogueira
rodrigobnogueira merged commit 0ebce6f into main Jul 20, 2026
1 check passed
@rodrigobnogueira
rodrigobnogueira deleted the feat/stalefree-cache branch July 20, 2026 00:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant